/**
 *
 */
package com.wedroid.r2d2.message.handler;

import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.wedroid.entity.message.MessageType;
import com.wedroid.r2d2.message.RipeMessage;

/**
 * @author lute
 */
@Component("compositeMessageHandler")
public class CompositeMessageHandler implements MessageHandler, Runnable, InitializingBean {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private List<MessageHandler> messageHandlers;

    private BlockingQueue<RipeMessage> messageQueue = new LinkedBlockingQueue<>();

    /* (non-Javadoc)
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
        new Thread(this).start();
    }

    /* (non-Javadoc)
     * @see com.wedroid.r2d2.message.handler.MessageHandler#handleMessage(com.wedroid.r2d2.message.RipeMessage)
     */
    public void handleMessage(RipeMessage ripeMessage) {

        logger.trace("#handleMessage - Get message ......");
        logger.trace("#handleMessage - ------------------------------");
        logger.trace("#handleMessage - | message id: {}", ripeMessage.getMsgId());
        logger.trace("#handleMessage - | message type: {}", ripeMessage.getMessageType());
        logger.trace("#handleMessage - | message from contact: {}", ripeMessage.getSenderDisplayName());
        if (ripeMessage.getSender().isGroup()) {
            logger.trace("#handleMessage - | message from user: {}", ripeMessage.getFromUserDisplayName());
        }
        logger.trace("#handleMessage - | message to contact: {}", ripeMessage.getReceiverDisplayName());
        logger.trace("#handleMessage - | message content: {}", ripeMessage.getData());
        logger.trace("#handleMessage - ------------------------------");

        // Do not handle Status_NOTIFY message
        if (!ripeMessage.getMessageType().equals(MessageType.STATYS_NOTIFY)) {
            try {
                messageQueue.add(ripeMessage);
            } catch (Exception e) {
                logger.error("#handleMessage - Adding message into queue encounters exception: {}", e);
            }
        }
    }

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        // Simply take message from queue and handle
        while (true) {
            try {
                final RipeMessage message = messageQueue.take();

                for (MessageHandler handler : messageHandlers) {
                    handler.handleMessage(message);
                }
            } catch (InterruptedException e) {
                logger.error("#run - Taking message from queue encounters InterruptedException: {}", e);
            } catch (Throwable throwable) {
                logger.error("#run - Handling message encounters some exception: {}", throwable);
            }
        }
    }

}
